package com.mazaiting.blog.utils

import com.mazaiting.blog.domain.Article
import java.io.*
import java.nio.charset.Charset
import java.sql.Timestamp

/**
 * 文件操作工具类
 */
class FileUtil {

    companion object {
        /**文章文件夹*/
        private const val FILE_DIR: String = "../resources/blog/"
        /**根文件夹路径*/
        private var dirPath = FileUtil::class.java.classLoader.getResource(FILE_DIR).path
        /**
         * 获取
         * @param author 作者
         * @return 文章列表
         */
        fun articleList(author: String): List<Article> = this.articleList(author, null)

        /**
         * 获取
         * @param author 作者
         * @param category 文章分类
         * @return 返回文章列表
         */
        fun articleList(author: String, category: String?): List<Article> {
            // 判断分类是否为空
            val hasCategory = (null != category && "" != category)
            // 根据分类是否为空来创建文件路径
            val filePath = if (hasCategory) (author + File.separatorChar + category) else author
            // 获取文件
            val file = File(dirPath, filePath)
            // 判断文件夹是否存在, 并且是文件夹
            return if (file.exists() && file.isDirectory) {
                // 获取文件列表
                val listFiles = file.listFiles()
                val list = ArrayList<Article>()
                // 遍历文件列表
                for (listFile in listFiles) {
                    list.add(Article(listFile.name, 1, (if (hasCategory) 1 else 1),
                            Timestamp(listFile.lastModified())))
                }
                list
            } else emptyList()
        }

        /**
         * 根据文件路径读取文件
         * @param author 作者
         * @param category 分类
         * @param fileName 文件名
         * @return 文章对象
         */
        fun readFile(author: String, category: String, fileName: String): Article? {
            // 文章地址
            val path = "$author/$category/$fileName"
            // 文件
            val file = File(dirPath, path)
            // 判断文件是否存在
            return if (file.exists() && !file.isDirectory) {
                Article(file.name, 1, file.length(), 1,
                        Timestamp(file.lastModified()), fileForReader(file))
            } else null
        }

        /**
         * BufferedReader读取文件
         * @param file 文件
         * @return Markdown文件内容
         */
        private fun fileForReader(file: File): String {
            // 按行读取
            val reader = BufferedReader(FileReader(file))
            val builder = StringBuilder()
            // 读取一行
            var line = reader.readLine()
            // 循环读取数据
            while (line != null) {
                // 拼接数据
                builder.append(line).append('\n')
                line = reader.readLine()
            }
            // 关闭文件流
            reader.close()
            return builder.toString()
        }

        /**
         * 创建用户对应的文件夹
         * @param author 用户名
         * @return true: 文件夹创建成功；false: 文件夹创建失败
         */
        fun create(author: String): Boolean = this.create(author, "")

        /**
         * 创建用户对应的文件夹
         * @param author 用户名
         * @param category 分类
         * @return true: 文件夹创建成功；false: 文件夹创建失败
         */
        fun create(author: String, category: String): Boolean = this.create(author, category, "")

        /**
         * 创建用户对应的文件夹
         * @param author 用户名
         * @param category 分类
         * @param fileName 文件名
         * @return true: 文件夹创建成功；false: 文件夹创建失败
         */
        fun create(author: String, category: String, fileName: String): Boolean {
            // 路径默认值为作者名
            var path = author
            // 判断分类是否为空
            if (!TextUtil.isEmpty(category)) {
                // 拼接分类路径
                path += File.separatorChar + category
                // 判断文件名是否为空
                if (!TextUtil.isEmpty(fileName)) {
                    // 凭借文件名
                    path += File.separatorChar + fileName + ".md"
                    // 获取文件
                    val file = File(dirPath, path)
                    // 创建文件
                    return file.createNewFile()
                }
            }
            // 获取文件
            val file = File(dirPath, path)
            // 判断文件夹是否存在
            return file.mkdir()
        }

        /**
         * 检查作者/分类/文件是否存在
         * @param author 作者
         * @return true: 存在；false: 不存在
         */
        fun check(author: String): Boolean = this.check(author, "")

        /**
         * 检查作者/分类/文件是否存在
         * @param author 作者
         * @param category 分类
         * @return true: 存在；false: 不存在
         */
        fun check(author: String, category: String): Boolean = this.check(author, category, "")

        /**
         * 检查作者/分类/文件是否存在
         * @param author 作者
         * @param category 分类
         * @param fileName 文件名
         * @return true: 存在；false: 不存在
         */
        fun check(author: String, category: String, fileName: String): Boolean {
            // 路径默认值为作者名
            var path = author
            // 判断分类是否为空
            if (!TextUtil.isEmpty(category)) {
                // 拼接分类路径
                path += File.separatorChar + category
                // 判断文件名是否为空
                if (!TextUtil.isEmpty(fileName)) {
                    // 凭借文件名
                    path += File.separatorChar + fileName + ".md"
                    val file = File(dirPath, path)
                    // 文件不存在，并且文件不是路径
                    return file.exists() && !file.isDirectory
                }
            }
            val file = File(dirPath, path)
            // 文件不存在，并且文件是路径
            return file.exists() && file.isDirectory
        }

        /**
         * 更新文件内容
         */
        fun update(author: String, category: String, fileName: String, content: String): String {
            // 文件路径
            val path = author + File.separatorChar + category + File.separatorChar + fileName + ".md"
            // 创建文件
            val file = File(dirPath, path)
            // 判断文件是否, 存在则删除，不存在则创建
            if (file.exists()) file.delete()
            else file.createNewFile()
            return this.saveData(file, content)
        }

        /**
         * 保存数据
         */
        private fun saveData(file: File, content: String): String {
            return try {
                val fos = FileOutputStream(file)
                fos.write(content.toByteArray(Charset.defaultCharset()))
                fos.close()
                "存储成功"
            } catch (e: Exception) {
                "存储异常"
            }
        }
    }
}